package com.hunan.api.catv.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * http请求
 *
 * @author ningzuojun
 */
public class HttpUtils {
    /**
     * logger
     */
    private static final Logger logger = Logger.getLogger(HttpUtils.class);
    private static final Logger requestLog = Logger.getLogger("Client");
    // 设置连接超时时间
    private final static int CONNECTTIMEOUT = 5000;
    // 设置请求超时时间
    private final static int CONNECTIONREQUESTTIMEOUT = 5000;
    // 读取请求超时时间
    private final static int SOCKETTIMEOUT = 5000;
    private static RequestConfig requestConfig = null;

    /**
     * 初始化设置超时时间
     *
     * @return
     */
    static {
        requestConfig = RequestConfig.custom().setConnectTimeout(CONNECTTIMEOUT) // 设置连接超时时间
                .setConnectionRequestTimeout(CONNECTIONREQUESTTIMEOUT) // 设置请求超时时间
                .setSocketTimeout(SOCKETTIMEOUT).setRedirectsEnabled(true)// 默认允许自动重定向
                .build();
    }

    /**
     * 重试请求
     */
    public static JSONObject retryHttpGet(String url, int retryTimes) {
        int currentTimes = 0;
        JSONObject jsonObject = null;
        while (currentTimes < retryTimes && jsonObject == null) {
            jsonObject = httpGet(url);
            currentTimes++;
        }
        return jsonObject;
    }


    /**
     * 发送get请求(返回参数为json格式处理)
     *
     * @param url
     * @return
     */
    public static JSONObject httpGet(String url) {
        // get请求返回结果
        JSONObject jsonResult = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            // 发送get请求
            HttpGet request = new HttpGet(url);
            request.setConfig(requestConfig);
            HttpResponse response = (HttpResponse) httpClient.execute(request);

            /** 请求发送成功，并得到响应 **/
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                /** 读取服务器返回过来的json字符串数据 **/
                String strResult = EntityUtils.toString(((org.apache.http.HttpResponse) response).getEntity());
                /** 把json字符串转换成json对象 **/
                jsonResult = JSONObject.parseObject(strResult);
                url = URLDecoder.decode(url, "UTF-8");
            } else {
                logger.error("get请求提交失败:" + url);
            }
        } catch (IOException e) {
            logger.error("get请求提交失败,url:" + url, e);
        } finally {
            requestLog.info("请求外部系统url:" + url + "|output:" + (null == jsonResult ? "" : jsonResult.toJSONString()));
            try {
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("发起httpClient请求异常:", e);
            }
        }
        return jsonResult;
    }

    /**
     * post请求(发送为json字符串格式 {"a":"1","b":"2","c":"3"})
     *
     * @param url       url地址
     * @param jsonParam 参数
     * @return
     */
    public static JSONObject httpPost(String url, String jsonParam) {
        // post请求返回结果
        CloseableHttpClient httpClient = HttpClients.createDefault();
        JSONObject jsonResult = null;
        HttpPost method = new HttpPost(url);
        try {
            method.setConfig(requestConfig);
            if (null != jsonParam) {
                // 解决中文乱码问题
                StringEntity entity = new StringEntity(jsonParam, "utf-8");
                entity.setContentEncoding("UTF-8");
                entity.setContentType("application/json");
                method.setEntity(entity);
            }
            HttpResponse result = httpClient.execute(method);
            url = URLDecoder.decode(url, "UTF-8");
            /** 请求发送成功，并得到响应 **/
            if (result.getStatusLine().getStatusCode() == 200) {
                String str = "";
                try {
                    /** 读取服务器返回过来的json字符串数据 **/
                    str = EntityUtils.toString(result.getEntity());
                    /** 把json字符串转换成json对象 **/
                    jsonResult = JSONObject.parseObject(str);
                } catch (Exception e) {
                    logger.error("post请求提交失败:" + url, e);
                }
            }
        } catch (IOException e) {
            logger.error("post请求提交失败,url:" + url, e);
        } finally {
            requestLog.info("url:" + url + "|请求参数:" + jsonParam + "|output:"
                    + (jsonResult == null ? "" : jsonResult.toJSONString()));
            try {
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (Exception e) {
                logger.error("关闭httpClient异常:", e);
            }
        }
        return jsonResult;
    }

    /**
     * 拼接字符串格式请求 a=1&b=2&c=3格式
     *
     * @param url
     * @param param_Map
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static JSONObject httpPost(String url, Map<String, String> param_Map) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setConfig(requestConfig);
            // 建立HttpPost对象
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            // 建立一个NameValuePair数组，用于存储欲传送的参数
            for (Map.Entry<String, String> entry : param_Map.entrySet()) {
                params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            // 添加参数
            httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            // 设置编码
            HttpResponse response = httpClient.execute(httppost);
            // 发送Post,并返回一个HttpResponse对象
            if (response.getStatusLine().getStatusCode() == 200) {// 如果状态码为200,就是正常返回
                result = EntityUtils.toString(response.getEntity());
            }
        } catch (Exception e) {
            logger.error("http提交post请求异常,url:" + url + "对方系统接口返回值:" + result, e);
        } finally {
            requestLog.info("接口url:" + url + "|请求参数:" + JSON.toJSONString(param_Map) + "|output:" + result);
            try {
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("关闭httpClient连接异常:", e);
            }
        }
        return JSONObject.parseObject(result);
    }


    /**
     * 拼接字符串格式请求 a=1&b=2&c=3格式
     */
    public static JSONObject httpPostWithoutJson(String url, Map<String, Object> param_Map) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setConfig(requestConfig);
            // 建立HttpPost对象
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            // 建立一个NameValuePair数组，用于存储欲传送的参数
            for (Map.Entry<String, Object> entry : param_Map.entrySet()) {
                params.add(new BasicNameValuePair(entry.getKey(), entry.getValue() + ""));
            }
            // 添加参数
            httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            // 设置编码
            HttpResponse response = httpClient.execute(httppost);
            // 发送Post,并返回一个HttpResponse对象
            if (response.getStatusLine().getStatusCode() == 200) {// 如果状态码为200,就是正常返回
                result = EntityUtils.toString(response.getEntity());
            }
        } catch (Exception e) {
            logger.error("http提交post请求异常,url:" + url + "对方系统接口返回值:" + result, e);
        } finally {
            requestLog.info("接口url:" + url + "|请求参数:" + JSON.toJSONString(param_Map) + "|output:" + result);
            try {
                if (null != httpClient) {

                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("关闭httpClient连接异常:", e);
            }
        }
        return JSONObject.parseObject(result);
    }

    /**
     * 定向流量请求
     *
     * @param url
     * @return
     */
    public static JSONObject headGet(String url) {
        // get请求返回结果
        JSONObject object = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            // 发送get请求
            HttpGet request = new HttpGet(url);
            request.setConfig(requestConfig);
            /** 请求发送成功，并得到响应 **/
            HttpResponse response = (HttpResponse) httpClient.execute(request);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                object = new JSONObject();
                String freeUrl = EntityUtils.toString(((org.apache.http.HttpResponse) response).getEntity());
                String header = response.getFirstHeader("X-Meteors").getValue();
                object.put("header", header);
                object.put("freeUrl", freeUrl);
            }
        } catch (Exception e) {
            logger.error("get请求提交失败,url:" + url, e);
        } finally {
            requestLog.info("请求外部系统url:" + url + "|output:" + (null == object ? "定向流量请求失败！" : object));
            try {
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("发起httpClient请求异常:", e);
            }
        }
        return object;
    }

    /**
     * 拼接字符串格式请求 a=1&b=2&c=3格式
     *
     * @param url
     * @param param_Map
     * @return
     * @throws ParseException
     * @throws IOException
     */
    public static String httpPostGetString(String url, Map<String, String> param_Map) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String result = "";
        try {
            HttpPost httppost = new HttpPost(url);
            httppost.setConfig(requestConfig);
            // 建立HttpPost对象
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            // 建立一个NameValuePair数组，用于存储欲传送的参数
            for (Map.Entry<String, String> entry : param_Map.entrySet()) {
                params.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            // 添加参数
            httppost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
            // 设置编码
            HttpResponse response = httpClient.execute(httppost);
            // 发送Post,并返回一个HttpResponse对象
            if (response.getStatusLine().getStatusCode() == 200) {// 如果状态码为200,就是正常返回
                result = EntityUtils.toString(response.getEntity());
            }
        } catch (Exception e) {
            logger.error("http提交post请求异常,url:" + url + "对方系统接口返回值:" + result, e);
        } finally {
            requestLog.info("接口url:" + url + "|请求参数:" + JSON.toJSONString(param_Map) + "|output:" + result);
            try {
                if (null != httpClient) {
                    httpClient.close();
                }
            } catch (IOException e) {
                logger.error("关闭httpClient连接异常:", e);
            }
        }
        return result;
    }

}
